package org.stone.project.zookeeper.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.CreateBuilder;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;
import org.apache.zookeeper.CreateMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.Charset;
import java.util.List;

@Component
public class ZookeeperTemplate {
    @Autowired
    private CuratorFramework curatorFramework;

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 获取子节点
     * @param path
     * @return
     * @throws Exception
     */
    public List<String> selectChildNode(String path) throws Exception {
        return curatorFramework.getChildren().forPath(path);
    }

    /**
     * 获取节点数据
     * @param path
     * @param clazz
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T> T getPathData(String path,Class<T> clazz) throws Exception {
        byte[] bytes = curatorFramework.getData().forPath(path);
        return objectMapper.readValue(new String(bytes, Charset.forName("UTF-8")),clazz);
    }

    /**
     * 获取数组数据节点
     * @param path
     * @param clazz
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T> List<T> getPathDataList(String path,Class<T> clazz) throws Exception {
        byte[] bytes = curatorFramework.getData().forPath(path);
        return objectMapper.readValue(new String(bytes, Charset.forName("UTF-8")), new TypeReference<List<T>>(){});
    }


    /**
     * 节点设置数据
     * @param path
     * @param data
     * @param <T>
     * @throws Exception
     */
    public <T> void setData(String path,T data,Boolean tmp) throws Exception {
        curatorFramework.setData().forPath(path,objectMapper.writeValueAsString(data).getBytes());
    }

    /**
     * 创建节点
     * @param path
     */
    public <T> String createNode(String path,T data,CreateMode createMode) throws Exception {
        byte[] persitentData = null;
        if (data != null){
            persitentData = objectMapper.writeValueAsString(data).getBytes();
        }
        CreateBuilder createBuilder = curatorFramework.create();
        createBuilder.withMode(createMode);
        return createBuilder.forPath(path,persitentData);
    }

    /**
     * 删除节点
     * @param path
     * @throws Exception
     */
    public void deleteNode(String path) throws Exception {
        curatorFramework.delete()
                .deletingChildrenIfNeeded()
                .forPath(path);
    }

    /**
     * 创建可重入排他锁(防止单机死锁)
     * @param path
     * @return
     */
    public InterProcessMutex getInterProcessMutex(String path){
        return new InterProcessMutex(curatorFramework,path);
    }

    /**
     * 创建不可重入共享锁(分布式资源竞争)
     * @param path
     * @return
     */
    public InterProcessSemaphoreMutex getInterProcessSemaphoreMutex(String path){
        return new InterProcessSemaphoreMutex(curatorFramework,path);
    }

    /**
     * 创建读写锁
     * @param path
     * @return
     */
    public InterProcessReadWriteLock getInterProcessReadWriteLock(String path){
        return new InterProcessReadWriteLock(curatorFramework,path);
    }
}
